// Node.js 回调函数
// Node.js 异步编程的直接体现就是回调。
// 异步编程依托于回调来实现，但不能说使用了回调后程序就异步化了。
// 回调函数在完成任务后就会被调用，Node 使用了大量的回调函数，Node 所有 API 都支持回调函数。
// 例如，我们可以一边读取文件，一边执行其他命令，在文件读取完成后，我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能，可以处理大量的并发请求。
//
// 回调函数一般作为参数的最后一个参数出现：
// function foo1(name, age, callback) { }
// function foo2(value, callback1, callback2) { }

// 引入fs模块
const fs = require('fs');

// 阻塞代码实例
var data = fs.readFileSync("../files/a.txt");
console.log(data.toString());
console.log("程序执行结束!\n-----------------------------------------");

// 非阻塞代码实例
// 执行异步操作的函数将回调函数作为最后一个参数， 回调函数接收错误对象作为第一个参数。
fs.readFile("../files/a1.txt",function (error,data){
   if(error){
       return console.error(error);
   }
   console.log(data.toString());
});
console.log("程序执行结束!");


// 阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行完程序。 第二个实例我们不需要等待文件读取完，这样就可以在读取文件时同时执行接下来的代码，大大提高了程序的性能。
// 因此，阻塞是按顺序执行的，而非阻塞是不需要按顺序的，所以如果需要处理回调函数的参数，我们就需要写在回调函数内。

// 阻塞和非阻塞，同步和异步是node.js里经常遇到的词汇，我举个简单的例子来说明：
// 我要看足球比赛，但是妈妈叫我烧水，电视机在客厅，烧水要在厨房。家里有2个水壶，一个是普通的水壶，另一个是水开了会叫的那种水壶。我可以：
//
// 1.用普通的水壶烧，人在边上看着，水开了再去看球。（同步，阻塞）这个是常规做法，但是我看球不爽了。
// 2.用普通水壶烧，人去看球，隔几分钟去厨房看看。（同步，非阻塞）这个又大问题，万一在我离开的几分钟水开了，我就麻烦了。
// 3.用会叫的水壶，人在边上看着。（异步，阻塞）这个没有问题，但是我太傻了。
// 4.用会叫的水壶，人去看球，听见水壶叫了再去看。（异步，非阻塞）这个应该是最好的。
//
// 等着看球的我：阻塞
// 看着电视的我：非阻塞
// 普通水壶：同步
// 会叫的水壶：异步
//
// 所以，异步往往配合非阻塞，才能发挥出威力。